<template>
  <AuModal
    v-model="showImportModal"
    :title="t('formula_detail.import_title')"
    width="70vw"
    height="70vh"
    :padding="false"
    :confirmTitle="t('formula_detail.import_confirm')"
    @handleConfirm="handleConfirm"
    @close="handleClose"
  >
    <div class="h-full pt-[16px]">
      <div class="flex justify-between items-center px-[1rem]">
        <div>
          <el-button type="primary" plain @click="fileInput?.click()"
            >{{ t("formula_detail.click_upload") }}
          </el-button>
          <input
            ref="fileInput"
            :key="inputKey"
            type="file"
            accept=".xlsx,.xls"
            style="display: none"
            @change="fileChanged"
          />
        </div>
        <el-button type="primary" link @click="fileDownload"
          >{{ t("formula_detail.example_download") }}
        </el-button>
      </div>
      <div class="h-[calc(100%_-_40px)]">
        <AuTable
          ref="tableRef"
          v-bind="gridOption"
          @checkboxChange="checkboxChange"
        >
          <template #status_default="{ row }">
            <el-tag :type="row.itemStatus ? 'success' : 'danger'" plain
              >{{
                row.itemStatus
                  ? t("formula_detail.normal")
                  : t("formula_detail.abnormal")
              }}
            </el-tag>
          </template>
          <template #error_default="{ row }">
            <span
              :class="{
                'text-red-500': !row.itemStatus,
                'text-green-500': row.itemStatus
              }"
              >{{ row.errorStr }}
            </span>
          </template>
        </AuTable>
      </div>
    </div>

    <template #footer_left>
      <span
        >{{ t("formula_detail.import_success")
        }}<b class="text-green-500">{{ successCount }}</b></span
      >&emsp;
      <span
        >{{ t("formula_detail.import_failed")
        }}<b class="text-red-500">{{ errorCount }}</b></span
      >
    </template>
  </AuModal>
</template>

<script lang="ts">
import {
  computed,
  defineComponent,
  getCurrentInstance,
  nextTick,
  PropType,
  reactive,
  ref
} from "vue";
import {
  ACTION_TYPE,
  ObjectProps,
  PropDefines
} from "@/components/AuTable/type";
import { AuTable } from "@/components/AuTable";
import { AuModal } from "@/components/AuModal";
import * as XLSX from "xlsx";
import { RegInt, Unique, UniqueArray } from "@/utils/tool";
import {
  formulaAddCheck,
  formulaAddImport,
  formulaDelete,
  FormulaDetailProp
} from "@/api/cabinet/formulaDetail";
import { ElMessage } from "element-plus";
import { isArray, isNullOrUnDef, isObject } from "@pureadmin/utils";
import { cloneDeep, pick } from "lodash-unified";
import { useI18n } from "vue-i18n";

interface RowData {
  [key: string]: string | number | boolean;
}

export default defineComponent({
  name: "ExcelImport",
  components: { AuModal, AuTable },
  props: {
    modelValue: {
      type: Boolean,
      default: false
    },
    version: {
      type: String,
      default: ""
    },
    tableData: {
      type: Array as PropType<any[]>,
      default: () => []
    }
  },
  emit: ["update:modelValue", "confirm"],
  setup(props, { emit }) {
    const { proxy } = getCurrentInstance();
    const { t } = useI18n();

    const fileInput = ref<HTMLInputElement>();
    const inputKey = ref(Date.now());
    const successCount = ref(0);
    const errorCount = ref(0);
    const tableRef = ref();
    const showImportModal = computed({
      get() {
        return props.modelValue;
      },
      set(value) {
        emit("update:modelValue", value);
      }
    });

    const gridOption = reactive<PropDefines>({
      isServerPage: false,
      showCheckbox: true,
      showIndex: false,
      showExportBtn: false,
      columns: [
        {
          field: "index",
          title: "formula_detail.serial_number",
          minWidth: 50,
          align: "center"
        },
        {
          field: "name",
          title: "formula_detail.formula_name",
          minWidth: 150,
          align: "center"
        },
        {
          field: "tag_list",
          title: "formula_detail.formula_tag",
          minWidth: 150,
          align: "center",
          formatter({ cellValue }) {
            return cellValue.map(v => v.name).join(",");
          }
        },
        {
          field: "spec",
          title: "formula_detail.formula_spec",
          minWidth: 150,
          align: "center"
        },
        {
          field: "materialAmount",
          title: "formula_detail.material_usage",
          minWidth: 150,
          align: "center",
          formatter({ cellValue }) {
            return cellValue
              .map(v => `${v.material_name}-${v.amount}`)
              .join(",");
          }
        },
        // {
        //   field: "material",
        //   title: "用量",
        //   minWidth: 150,
        //   align: "center"
        // },
        // {
        //   field: "publish_status",
        //   title: "配方状态",
        //   minWidth: 150,
        //   align: "center"
        // },
        {
          field: "third_value",
          title: "formula_detail.external_id",
          minWidth: 150,
          align: "center"
        },
        {
          field: "errorStr",
          title: "formula_detail.upload_status",
          minWidth: 180,
          align: "center",
          showOverflow: false,
          slots: {
            default: "error_default"
          }
        }
      ],
      actions: [],
      operateTools: [],
      dataSource: [],
      vxeTableConfig: {
        checkboxConfig: {
          checkMethod({ row }) {
            return !row.errorStr;
          }
        },
        pagerConfig: {
          enabled: false
        }
      }
    });

    function splitCellRange(rangeStr: string) {
      const parts = rangeStr.split(":");
      const startPart = parts[0];
      const endPart = parts[1];

      const startColumn = startPart.match(/[A-Z]+/i)[0];
      const startRow = startPart.match(/\d+/)[0];
      const endColumn = endPart.match(/[A-Z]+/i)[0];
      const endRow = endPart.match(/\d+/)[0];

      return {
        startColumn,
        startRow,
        endColumn,
        endRow
      };
    }

    function customEncode(str: string) {
      let result = 0;
      for (let i = 0; i < str.length; i++) {
        const charCode = str.charCodeAt(i) - "A".charCodeAt(0) + 1;
        result = result * 26 + charCode;
      }
      return result;
    }

    function numberToLetters(num: number) {
      let result = "";
      while (num > 0) {
        let remainder = (num - 1) % 26; // 计算余数
        result = String.fromCharCode(65 + remainder) + result; // 将余数转换为对应的字母并添加到结果字符串的开头
        num = Math.floor((num - 1) / 26); // 更新num为下一个基数减去的数
      }
      return result;
    }

    function getDataSource(dataSource: any[]) {
      const fetchParam = [];
      for (let i = 0; i < dataSource.length; i++) {
        const item = dataSource[i];
        const paramIndex = fetchParam.findIndex(
          v => v.name === dataSource[i].name
        );
        const materialSpecs = item.spec.split("-").map(v => ({ attr: v }));
        const specification_list = item.spec
          .split("-")
          .map(v => ({ check_attr: v }));
        if (paramIndex !== -1) {
          const findContent = fetchParam[paramIndex];
          findContent.formula_detail.push({
            materialSpecs,
            materialAmount: item.materialAmount
          });
          for (let j = 0; j < specification_list.length; j++) {
            const curSpec = findContent.specification_list[j];
            if (curSpec.check_attr !== specification_list[j].check_attr) {
              curSpec.check_attr += "," + specification_list[j].check_attr;
            }
          }
        } else {
          const content = {
            ...item,
            version: props.version,
            specification_list,
            material_list: item.materialAmount.map(v => ({
              name: v.material_name,
              index: 1
            })),
            formula_detail: [
              {
                materialSpecs,
                materialAmount: item.materialAmount
              }
            ],
            is_auto: false,
            device_type: "柜式机"
          };
          fetchParam.push(content);
        }
      }
      const getKeys = [
        "icon",
        "name",
        "tag_list",
        "third_value",
        "note",
        "version",
        "formula_version",
        "material_list",
        "specification_list",
        "formula_detail",
        "publish_status",
        "is_auto",
        "device_type"
      ];
      return fetchParam.map(v => {
        const data = pick(v, getKeys);
        for (const key in data) {
          if (isArray(data[key]) || isObject(data[key])) {
            data[key] = JSON.stringify(data[key]);
          }
        }
        return data;
      });
    }

    function readExcelFile(sheet: any) {
      // 定义行和列的范围
      const rowStart = 3;
      const colStart = "B"; // B列
      console.log(Object.keys(sheet));
      const { endColumn: colEnd, endRow: rowEnd } = splitCellRange(
        sheet["!ref"]
      );

      // 初始化一个空数组来存储数据组
      let dataList: RowData[] = [];

      const specKeyLen = {};
      // 遍历列
      console.log(
        customEncode(colStart),
        customEncode(colEnd),
        colStart,
        colEnd
      );
      for (
        let col = customEncode(colStart);
        col <= customEncode(colEnd);
        col++
      ) {
        let dataGroup: any = {
          itemStatus: true,
          errorStr: "",
          specErr: false,
          publish_status: 1,
          index: sheet[`${numberToLetters(col)}${rowStart - 1}`]?.v ?? col - 1 // 使用B2, C2...单元格写的索引，如果没有写索引，则默认取遍历索引
        };
        let formulaDetail = [];
        console.log(col, colStart.charCodeAt(0), colEnd.charCodeAt(0));

        // 遍历行
        for (let row = rowStart; row <= Number(rowEnd); row++) {
          const cellAddress = `${numberToLetters(col)}${row}`;
          const cellValue = sheet[cellAddress] ? sheet[cellAddress].v : "";

          // 根据行号组织数据
          if (row === rowStart) {
            dataGroup.name = cellValue;
            if (!dataGroup.name) {
              dataGroup.itemStatus = false;
              dataGroup.errorStr += t("formula_detail.name_empty_error") + "\n";
            }
          } else if (row === rowStart + 1) {
            dataGroup.third_value = cellValue;
          } else if (row === rowStart + 2) {
            dataGroup.spec = cellValue;
            const len = dataGroup.spec.split("-").length;
            if (isNullOrUnDef(specKeyLen[dataGroup.name])) {
              specKeyLen[dataGroup.name] = dataGroup.spec.split("-").length;
            } else {
              if (specKeyLen[dataGroup.name] != len) {
                dataGroup.specErr = true;
                dataGroup.itemStatus = false;
                dataGroup.errorStr +=
                  t("formula_detail.spec_count_error") + "\n";
              }
            }
          } else if (row === rowStart + 3) {
            // 标签去除空的 处理为 [{name: ""}]
            dataGroup.tag_list = cellValue
              .split(/[,，|]/)
              .filter(tag => tag)
              .map(tag => ({
                name: tag
              }));
          } else if (row >= rowStart + 4) {
            // 物料名称和数量从第五行开始
            const [materialName, amount] = cellValue.split("-");
            if (materialName && amount) {
              formulaDetail.push({
                index: 1,
                material_name: materialName,
                amount,
                amount_unit: "g"
              });
            } else if (!materialName && amount) {
              dataGroup.itemStatus = false;
              dataGroup.errorStr +=
                t("formula_detail.material_name_missing", {
                  row: rowStart + 5 - row
                }) + "\n";
            } else if (!amount && materialName) {
              dataGroup.itemStatus = false;
              dataGroup.errorStr +=
                t("formula_detail.material_amount_missing", {
                  row: rowStart + 5 - row
                }) + "\n";
            }
          }
        }

        // 添加配方详情
        if (formulaDetail.length > 0) {
          dataGroup.materialAmount = formulaDetail;
        } else {
          dataGroup.itemStatus = false;
          dataGroup.errorStr += t("formula_detail.no_material_usage") + "\n";
        }
        // 判断是否有空的一列的情况
        if (dataGroup.name || dataGroup.spec || formulaDetail.length)
          dataList.push(dataGroup);
      }

      // 遍历数据组，判断是否有相同的配方名称中状态错误的情况
      for (let i = 0; i < dataList.length; i++) {
        const item = dataList[i];
        // 如果有一个规格错误，则将所有相同名称的规格错误
        if (item.specErr) {
          for (let j = 0; j < dataList.length; j++) {
            const handleItem = dataList[j];
            if (handleItem.name == item.name && !handleItem.specErr) {
              handleItem.specErr = true;
              handleItem.itemStatus = false;
              handleItem.errorStr +=
                t("formula_detail.spec_count_error") + "\n";
            }
          }
        }
        // 如果有错误，则将所有相同名称的打上错误标记
        if (!item.itemStatus) {
          for (let j = 0; j < dataList.length; j++) {
            const handleItem = dataList[j];
            if (handleItem.name == item.name) {
              handleItem.itemStatus = false;
              handleItem.errorStr += " "; // 为了让复选框禁用
            }
          }
        }

        // 判断是否有重复的规格
        for (let j = 0; j < dataList.length; j++) {
          const handleItem = dataList[j];
          const specHI = (handleItem.spec as string).split("-");
          const specI = (item.spec as string).split("-");
          const specList = Unique([...specHI, ...specI]);
          if (
            handleItem.name == item.name &&
            specList.length === specHI.length &&
            item.index !== handleItem.index &&
            !handleItem.specRepeat
          ) {
            handleItem.itemStatus = false;
            handleItem.specRepeat = true;
            handleItem.errorStr += t("formula_detail.spec_duplicate") + "\n";
          }
        }
      }

      console.log(dataList);

      const ds = getDataSource(dataList);
      formulaAddCheck(
        cloneDeep(ds).map(v => {
          for (const key in v) {
            if (isObject(v[key]) || isArray(v[key])) {
              v[key] = JSON.stringify(v[key]);
            }
          }
          return v;
        })
      ).then(res => {
        if (res.data.length) {
          for (const item of res.data) {
            if (!item.state) {
              dataList = dataList.map(v => {
                if (v.name === item.name) {
                  v.itemStatus = false;
                  v.errorStr += item.message;
                }
                return v;
              });
            }
          }
          gridOption.dataSource = dataList;
          nextTick(() => {
            const $table = tableRef.value;
            const list = dataList.filter(item => !item.errorStr);

            $table.vxeGridRef.setCheckboxRow(list, true);
          });
        }
      });
    }

    const fileChanged = () => {
      console.log(fileInput.value?.files);
      const file = fileInput.value.files[0];
      if (file) {
        const reader = new FileReader();
        successCount.value = 0;
        errorCount.value = 0;
        reader.onload = e => {
          const data = new Uint8Array(e.target.result as ArrayBuffer);
          const workbook = XLSX.read(data, { type: "array" });
          const firstSheetName = workbook.SheetNames[0];
          const worksheet = workbook.Sheets[firstSheetName];
          const json = XLSX.utils.sheet_to_json(worksheet, {
            header: 1
          }) as string[][];
          console.log(json, worksheet);
          // handleExcelData(json, worksheet);
          readExcelFile(worksheet);
          // if (checkExcelData(json)) {
          //   handleExcelData(json, worksheet);
          // }
          inputKey.value = Date.now();
        };
        reader.readAsArrayBuffer(file);
      }
    };

    const setSelectRow = (rows: Record<string, any>[], checked: boolean) => {
      const $table = tableRef.value;
      if ($table) {
        console.log($table.vxeGridRef, rows);
        nextTick(() => {
          $table.vxeGridRef.setCheckboxRow(rows, checked);
        });
      }
    };

    const checkboxChange = (list: Record<string, any>[], checkParam: any) => {
      // const $table = tableRef.value;
      if (!checkParam) return;
      // if ($table) {
      //   $table.vxeGridRef.setCheckboxRow(gridOption.dataSource, false);
      //   nextTick(() => {
      //     const checkList = gridOption.dataSource.filter(item => {
      //       return checkParam.row.name === item.name;
      //     });
      //     $table.vxeGridRef.setCheckboxRow(checkList, checkParam.checked);
      //   });
      // }
    };

    const handleConfirm = async () => {
      const dataSource = tableRef.value.getCheckboxRecords();
      if (!dataSource.length) {
        proxy.$message.error(t("formula_detail.select_import_data"));
        return;
      }

      const param = getDataSource(dataSource);
      console.log(param);

      const ds = cloneDeep(gridOption.dataSource);
      setSelectRow(ds, false);
      for (const item of param) {
        const filter = dataSource.filter(v => v.name === item.name);
        try {
          const find = props.tableData.find(v => v.name === item.name);
          if (find) {
            await formulaDelete({
              delList: JSON.stringify([find]),
              is_auto: true
            });
          }

          await formulaAddImport(item);
          for (const item of filter) {
            ds[item.index - 1].itemStatus = true;
            ds[item.index - 1].errorStr = "上传成功";
            successCount.value++;
          }
        } catch (error) {
          for (const item of filter) {
            ds[item.index - 1].itemStatus = false;
            ds[item.index - 1].errorStr += error.message;
            errorCount.value++;
          }
        }
      }
      gridOption.dataSource = ds;
      handleClose();
    };

    const handleClose = () => {
      emit("confirm");
    };

    const fileDownload = () => {
      const path = import.meta.env?.VITE_PUBLIC_PATH ?? "/admin/";
      // 使用 window.location.href 直接下载文件
      window.location.href = (path || "") + "/柜式机配方导入示例表.xlsx";

      // 或者使用 a 标签模拟点击下载
      // const link = document.createElement('a');
      // link.href = '/files/example.pdf';
      // link.download = 'example.pdf'; // 指定下载的文件名
      // document.body.appendChild(link);
      // link.click();
      // document.body.removeChild(link);
    };

    return {
      fileInput,
      inputKey,
      showImportModal,
      gridOption,
      successCount,
      errorCount,

      tableRef,

      fileChanged,
      handleConfirm,
      handleClose,
      fileDownload,
      checkboxChange,
      t
    };
  }
});
</script>
